import sys
import time
import http.client as http_lib
import urllib.parse as u
import urllib.request as u2
import urllib3 as u3
import requests

'''
    default_sc:默认进度回调函数
    default_urllib2_sc:默认进度回调函数[urllib2]
    
    DownloaderHttp:Http模块下载类
    DownloaderUrllib2:Urllib2模块下载类
    DownloaderRequests:Requests模块下载类
    
    RequesterHttp:Http模块请求类
    RequesterUrllib2:Urllib2模块请求类
    RequesterRequests:Requests模块请求类
    
    upload_requests:Requests文件上传函数
    upload_urllib2:Urllib2文件上传函数
    upload_urllib3:Urllib3文件上传函数
'''


def default_sc(total_size, finished_size):
    if total_size > 0:
        percent = float(finished_size) / total_size * 100
        old_size = total_size - finished_size
        speed = (finished_size - old_size) / 0.1
        print('%12d %12d %10.2f%% %12d' % (total_size, finished_size, percent, speed))
        time.sleep(0.1)


def default_urllib2_sc(read_num, read_size, total_size):
    percent = float(read_num) * read_size * 100 / total_size
    percent = '\r当前进度:' + '%.2f%%' % (percent if percent < 100 else 100)
    sys.stdout.write(percent)
    sys.stdout.flush()
    time.sleep(0.1)


class Downloader(object):
    def __init__(self, full_url_str, filename, sc=None):
        self.full_url = full_url_str
        self.url = u.urlparse(full_url_str)
        self.filename = filename
        self.sc = sc

    def start(self):
        if self.url == '' or self.url is None or self.filename == '' or self.filename is None:
            return

        self.download()

    def download(self):
        pass


class Requester(object):
    def __init__(self, full_url_str, method="GET"):
        self.full_url = full_url_str
        self.url = u.urlparse(full_url_str)
        self.method = method
        self.headers = {"User-Agent": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
        self.data = None

    def set_headers(self, headers):
        self.headers = headers

    def set_data(self, data):
        self.data = data

    def start(self):
        if self.url == '' or self.url is None:
            return None

        result = self.req()
        if result == "":
            return None

        return result

    def req(self):
        return ""


class DownloaderHttp(Downloader):

    def download(self):
        if self.url.scheme == 'https':
            conn = http_lib.HTTPSConnection(self.url.netloc)
        else:
            conn = http_lib.HTTPConnection(self.url.netloc)
        conn.request('GET', self.url.path)
        response = conn.getresponse()

        if response.status == 200:
            total_size = int(response.getheader('Content-Length'))
            if total_size > 0:
                finished_size = 0
                my_file = open(self.filename, 'wb')
                while not response.isclosed():
                    buffers = response.read(1024)
                    my_file.write(buffers)
                    finished_size += len(buffers)
                    if self.sc:
                        self.sc(total_size, finished_size)
                    if finished_size >= total_size:
                        break
                my_file.close()
        conn.close()


class DownloaderUrllib2(Downloader):

    def download(self):
        u2.urlretrieve(self.full_url, self.filename, self.sc)


class DownloaderRequests(Downloader):

    def download(self):
        mu = requests.get(self.full_url, stream=True)
        finished_size = 0
        with open(self.filename, 'wb') as m_file:
            content_size = int(mu.headers['content-length'])
            for chunk in mu.iter_content(chunk_size=512):
                if chunk:
                    finished_size += len(chunk)
                    m_file.write(chunk)
                    if self.sc:
                        self.sc(content_size, finished_size)
        mu.close()


class RequesterHttp(Requester):

    def req(self):
        if self.url.scheme == 'https':
            conn = http_lib.HTTPSConnection(self.url.netloc)
        else:
            conn = http_lib.HTTPConnection(self.url.netloc)

        conn.request(self.method, self.url.path, body=self.data, headers=self.headers)
        response = conn.getresponse()

        buffers = bytes()
        if response.status == 200:
            while not response.isclosed():
                buffers += response.read(1024)
        conn.close()
        return buffers.decode("utf-8")


class RequesterUrllib2(Requester):

    def req(self):
        request = u2.Request(self.full_url, data=self.data, headers=self.headers, method=self.method)
        response = u2.urlopen(request)

        page = bytes()
        if response.code == 200:
            page = response.read()
        response.close()

        return page.decode("utf-8")


class RequesterRequests(Requester):

    def req(self):
        request = requests.request(self.method, self.full_url, headers=self.headers, data=self.data)
        request.encoding = "utf-8"

        if request.status_code == 200:
            return request.text


def upload_requests(file_path, data=None, up_url="http://127.0.0.1:8081/api/upload"):
    file = {'file': open(file_path, 'rb')}
    r = requests.post(up_url, data=data, files=file)

    if r.status_code == 200:
        return r.text


def upload_urllib2(file_name: bytes, file_content, up_url="http://127.0.0.1:8081/api/upload"):
    boundary = "-----U3lzdGVtTGlnaHQ="
    headers = {"Content-Type": "multipart/form-data; boundary={}".format(boundary)}

    start_flag = b'-------U3lzdGVtTGlnaHQ=\r\nContent-Disposition: form-data; name="file"; '
    file_name = b'filename="' + file_name + b'"\r\n\r\n' + file_content + b'\r\n-------U3lzdGVtTGlnaHQ=--\r\n'

    request = u2.Request(up_url, start_flag + file_name, headers, method="POST")
    return u2.urlopen(request).read()


def upload_urllib3(file_path, file_name=None, up_url="http://127.0.0.1:8081/api/upload"):
    if file_name is None:
        file_name = file_path
    with open(file_path, 'rb') as fp:
        url = up_url
        boundary = "-----U3lzdGVtTGlnaHQ="
        headers = {"Content-Type": "multipart/form-data; boundary={}".format(boundary)}
        method = "POST"

        u3.disable_warnings()
        http = u3.PoolManager()
        result = http.request(method=method,
                              url=url,
                              headers=headers,
                              multipart_boundary=boundary,
                              fields={'file': (file_name, fp.read(), None)})
        return result.data


if __name__ == "__main__":
    # req = RequesterRequests("http://127.0.0.1:8081", "GET")
    # req.set_data('{"a":"b"}')
    # resp = req.start()
    # print(resp)
    print(upload_requests("./datetimeTool.py", data={"user_gid": "5e7ecceb-30b8-5bd2-b3f5-9d2c982c82ba"},
                          up_url="http://127.0.0.1:8081/api/upload_image"))
